#coding=utf-8

require "aio/core"

class Aio::Module::SpecialStyle::Compare < Aio::Module::SpecialStyle
  include Aio::Module

  include Aio::Ui::Verbose

  # 用于传递已经分析好的现有的device
  attr_accessor :device_manager

  # 用于传递由XML，Json生成并已经解析的Hash值
  attr_accessor :input_benchmark

  def initialize
    super({
      :author		=> "Elin",
      :description => "此模块用于解析两个Hash值的不同点,并发出警告",
    })
  end

  def parse
    # 将device_manager 中的按照{device_name => useful} 形式重新编排
    # cmds_useful为深度克隆信息，对本体无影响
    device_warning = {}
    total = device_manager.devices_number
    print_good "总共 #{total} 台设备进行比较"

    device_manager.each_devices_with_index do |device_name, device_klass, i|

      device_warning[device_name] = Aio::Base::Toolkit::DeepClone.clone(device_klass.cmds_useful)
      # 进度条
      progress_bar(total, i+1, device_name)

    end

    @compare_hash = Aio::Module::Compare.new
    clear_line

    clear_other_info(device_warning, input_benchmark)
    compare(device_warning, input_benchmark)
  end

  # 只留下要比较的两个数据有共同命令的交集,其他的命令就丢弃
  # 因为即使是保留了,产生的也是大量的垃圾信息
  def clear_other_info(device_warning, input_benchmark)
    device_arr = {}
    input_arr  = {}

    # 获得命令信息
    device_warning.each_pair 	{ |k, v| device_arr[k] = v.keys }
    input_benchmark.each_pair { |k, v| input_arr[k]  = v.keys }

    # 删除 device_warning 中多余的命令信息
    device_warning.each_pair do |name, hash|
      hash.delete_if do |k, v|
        next true unless input_arr.has_key?(name)
        input_arr[name].include?(k) ? false : true
      end
    end

    # 删除 input_benchmark 中多余的命令信息
    input_benchmark.each_pair do |name, hash|
      hash.delete_if do |k, v|
        next true unless device_arr.has_key?(name)
        device_arr[name].include?(k) ? false : true
      end
    end
  end

  def compare(cm1, cm2, opts={})
    # NOTE 待加PASS
    @config_compare = Aio::Config::Warning::Compare

    cm1_arr = []
    cm2_arr = []
    Aio::Base::Toolkit::Hash.flat(cm1,
                                  Aio::Base::Toolkit::Chain.new,
                                  cm1_arr)

    Aio::Base::Toolkit::Hash.flat(cm2,
                                  Aio::Base::Toolkit::Chain.new,
                                  cm2_arr)

    cp = find_diff(cm1_arr, cm2_arr)

    diff = { cm1: [], cm2: []}
    # NOTE 还需要加入config_compare
    # diff = {
    #    cm1: [ [device_name, cmd, str], .. ],
    #    cm2: [ [device_name, cmd, str], .. ]
    # }
    cp[:cm1].each do |e|
      # 加入cmd
      cmd = e[1]
      diff[:cm1] << [e.first, cmd, e.last]
    end

    cp[:cm2].each do |e|
      diff[e.first] ||= {}
      # 加入cmd
      cmd = e[1]
      diff[:cm2] << [e.first, cmd, e.last]
    end

    diff
  end

  def find_diff(cm1, cm2)
    res = {}
    res[:cm1] = []
    res[:cm2] = []

    # res 为相同的内容
    total = cm1.size
    cm1.each_with_index do |link_1, i|

      cm2.each do |link_2|

        # 如果长度不一致，就下一个
        if link_1.size != link_2.size
          next

        else
          name_1 = long_name(link_1)
          name_2 = long_name(link_2)

          if name_1 == name_2
            res[:cm1] << link_1
            res[:cm2] << link_2

            # 找到了相同的就跳出小循环
            break
          end

        end
      end

      # 进度条
      progress_bar(total, i+1, '')
    end

    clear_line

    # 获得不同的内容
    res[:cm1] = cm1 - res[:cm1]
    res[:cm2] = cm2 - res[:cm2]

    res
  end

  # 将一个数组转化成一长串字符作为比较方式
  def long_name(arr)
    res = ''
    arr.each { |x| res += x.to_s }
    res
  end

end
